/**
 ******************************************************************************
 * @file           : usbd_storage_if.c
 * @brief          : Memory management layer
 ******************************************************************************
 * COPYRIGHT(c) 2016 STMicroelectronics
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 * 1. Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 * 3. Neither the name of STMicroelectronics nor the names of its contributors
 * may be used to endorse or promote products derived from this software
 * without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 ******************************************************************************
 */

/* Includes ------------------------------------------------------------------*/
#include "usbd_storage_if.h"
/* USER CODE BEGIN INCLUDE */
#include "spi_flash.h"
#include "bsp_driver_sd.h"
/* USER CODE END INCLUDE */

/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
 * @{
 */

/** @defgroup USBD_STORAGE
 * @brief usbd core module
 * @{
 */

/** @defgroup USBD_STORAGE_Private_TypesDefinitions
 * @{
 */
/* USER CODE BEGIN PRIVATE_TYPES */
/* USER CODE END PRIVATE_TYPES */

/**
 * @}
 */

/** @defgroup USBD_STORAGE_Private_Defines
 * @{
 */
#define STORAGE_LUN_NBR         1
#define LUN0_STORAGE_BLK_NBR    (65535)
#define LUN0_STORAGE_BLK_SIZ    2048
#define STORAGE_BLK_NBR         0x10000
#define STORAGE_BLK_SIZ         0x200
/* USER CODE BEGIN PRIVATE_DEFINES */
/* USER CODE END PRIVATE_DEFINES */

/**
 * @}
 */

/** @defgroup USBD_STORAGE_Private_Macros
 * @{
 */
/* USER CODE BEGIN PRIVATE_MACRO */
/* USER CODE END PRIVATE_MACRO */

/**
 * @}
 */

/** @defgroup USBD_STORAGE_IF_Private_Variables
 * @{
 */
/* USER CODE BEGIN INQUIRY_DATA_FS */
/* USB Mass storage Standard Inquiry Data */
const int8_t STORAGE_Inquirydata_FS[] =   //36
{ /* LUN 0 */
  0x00,
  0x80,
  0x02,
  0x02,
  (STANDARD_INQUIRY_DATA_LEN - 5),
  0x00,
  0x00,
  0x00,
  'C',                            'O',  'O', 'L', 'S', 'A', 'V', 'E', /* Manufacturer : 8 bytes */
  'N',                            ',',  'U', 'D', 'I', 'S', 'K', ' ', /* Product      : 16 Bytes */
  ' ',                            ' ',  ' ', ' ', ' ', ' ', ' ', ' ',
  '0',                            '.',  '0', '1',                     /* Version      : 4 Bytes */
  /* LUN 1 */
  0x00,
  0x80,
  0x02,
  0x02,
  (STANDARD_INQUIRY_DATA_LEN - 5),
  0x00,
  0x00,
  0x00,
  'C',                            'O',  'O', 'L', 'S', 'A', 'V', 'E', /* Manufacturer : 8 bytes */
  'N',                            ',',  'U', 'D', 'I', 'S', 'K', ' ', /* Product      : 16 Bytes */
  ' ',                            ' ',  ' ', ' ', ' ', ' ', ' ', ' ',
  '0',                            '.',  '0', '1',                     /* Version      : 4 Bytes */
};
/* USER CODE END INQUIRY_DATA_FS */

/* USER CODE BEGIN PRIVATE_VARIABLES */
/* USER CODE END PRIVATE_VARIABLES */

/**
 * @}
 */

/** @defgroup USBD_STORAGE_IF_Exported_Variables
 * @{
 */
extern USBD_HandleTypeDef hUsbDeviceFS;
/* USER CODE BEGIN EXPORTED_VARIABLES */
/* USER CODE END EXPORTED_VARIABLES */

/**
 * @}
 */

/** @defgroup USBD_STORAGE_Private_FunctionPrototypes
 * @{
 */
static int8_t STORAGE_Init_FS(uint8_t lun);
static int8_t STORAGE_GetCapacity_FS(uint8_t  lun,
                                     uint32_t *block_num,
                                     uint16_t *block_size);
static int8_t STORAGE_IsReady_FS(uint8_t lun);
static int8_t STORAGE_IsWriteProtected_FS(uint8_t lun);
static int8_t STORAGE_Read_FS(uint8_t  lun,
                              uint8_t  *buf,
                              uint32_t blk_addr,
                              uint16_t blk_len);
static int8_t STORAGE_Write_FS(uint8_t  lun,
                               uint8_t  *buf,
                               uint32_t blk_addr,
                               uint16_t blk_len);
static int8_t STORAGE_GetMaxLun_FS(void);

/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */

/**
 * @}
 */

USBD_StorageTypeDef USBD_Storage_Interface_fops_FS =
{
  STORAGE_Init_FS,
  STORAGE_GetCapacity_FS,
  STORAGE_IsReady_FS,
  STORAGE_IsWriteProtected_FS,
  STORAGE_Read_FS,
  STORAGE_Write_FS,
  STORAGE_GetMaxLun_FS,
  (int8_t *)STORAGE_Inquirydata_FS,
};

/* Private functions ---------------------------------------------------------*/

/*******************************************************************************
* Function Name  : STORAGE_Init_FS
* Description    :
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
int8_t STORAGE_Init_FS(uint8_t lun)
{
  /* USER CODE BEGIN 2 */
  return(USBD_OK);
  /* USER CODE END 2 */
}


/*******************************************************************************
* Function Name  : STORAGE_GetCapacity_FS
* Description    :
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
{
  /* USER CODE BEGIN 3 */

  if (lun == 1)
  {
    *block_num = LUN0_STORAGE_BLK_NBR;
    *block_size = LUN0_STORAGE_BLK_SIZ;
    return(USBD_OK);
  }
  else
  {
    SD_CardInfo info;

    int8_t ret = -1;

    if (BSP_SD_IsDetected() != SD_NOT_PRESENT)
    {
      BSP_SD_GetCardInfo(&info);

      *block_num = (info.CardCapacity) / STORAGE_BLK_SIZ - 1;
      *block_size = STORAGE_BLK_SIZ;
      ret = 0;
    }
    return ret;
  }
  /* USER CODE END 3 */
}


/*******************************************************************************
* Function Name  : STORAGE_IsReady_FS
* Description    :
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
int8_t STORAGE_IsReady_FS(uint8_t lun)
{
  /* USER CODE BEGIN 4 */
  return(USBD_OK);
  /* USER CODE END 4 */
}


/*******************************************************************************
* Function Name  : STORAGE_IsWriteProtected_FS
* Description    :
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
int8_t STORAGE_IsWriteProtected_FS(uint8_t lun)
{
  /* USER CODE BEGIN 5 */
  return(USBD_OK);
  /* USER CODE END 5 */
}


/*******************************************************************************
* Function Name  : STORAGE_Read_FS
* Description    :
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
int8_t STORAGE_Read_FS(uint8_t  lun,
                       uint8_t  *buf,
                       uint32_t blk_addr,
                       uint16_t blk_len)
{
  /* USER CODE BEGIN 6 */
  if (lun == 1)
  {
    W25Nxx_ReadData(buf, blk_addr * LUN0_STORAGE_BLK_SIZ, blk_len / LUN0_STORAGE_BLK_SIZ + 1);
  }
  else
  {
    BSP_SD_ReadBlocks((uint32_t *)buf, blk_addr * STORAGE_BLK_SIZ, STORAGE_BLK_SIZ, blk_len);
  }

  return(USBD_OK);
  /* USER CODE END 6 */
}


/*******************************************************************************
* Function Name  : STORAGE_Write_FS
* Description    :
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
int8_t STORAGE_Write_FS(uint8_t  lun,
                        uint8_t  *buf,
                        uint32_t blk_addr,
                        uint16_t blk_len)
{
  /* USER CODE BEGIN 7 */
  if (lun == 1)
  {
    W25Nxx_WriteData(buf, blk_addr * LUN0_STORAGE_BLK_SIZ, blk_len / LUN0_STORAGE_BLK_SIZ + 1);
  }
  else
  {
    BSP_SD_WriteBlocks((uint32_t *)buf, blk_addr * STORAGE_BLK_SIZ, STORAGE_BLK_SIZ, blk_len);
  }
  return(USBD_OK);
  /* USER CODE END 7 */
}


/*******************************************************************************
* Function Name  : STORAGE_GetMaxLun_FS
* Description    :
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
int8_t STORAGE_GetMaxLun_FS(void)
{
  /* USER CODE BEGIN 8 */
  return(STORAGE_LUN_NBR - 1);
  /* USER CODE END 8 */
}


/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */

/**
 * @}
 */

/**
 * @}
 */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
